
#ifndef RT_USE_OLD_CONN_WRAP

#ifndef __RT_CONN_RLB_TCP_SENDBUFFER_H__
#define __RT_CONN_RLB_TCP_SENDBUFFER_H__

#include "RtNetworkBase.h"
#include "RtQueueT.h"
#include "RtConnRlbTcpPdu.h"
#include "RtMemoryPoolT.h"

class RlbTcpPduDataPoolType: public CRtMemoryPoolT<CRtConnRlbTcpPduData>
{
	typedef CRtMemoryPoolT<CRtConnRlbTcpPduData> BaseType;

public:
	RlbTcpPduDataPoolType()
		: BaseType("RlbTcpPduDataPool")
	{
		BaseType::Preallocate(64);
	}

private:
	RlbTcpPduDataPoolType(const RlbTcpPduDataPoolType&);
	RlbTcpPduDataPoolType& operator = (const RlbTcpPduDataPoolType&);
};

class CRtConnRlbTcp;

class CRtConnRlbTcpSendBuffer
{
public:
	typedef DataStructures::Queue<CRtConnRlbTcpPduData*> DataQueue;

	CRtConnRlbTcpSendBuffer(CRtConnRlbTcp* inConn);
	virtual ~CRtConnRlbTcpSendBuffer();

public:
	/// Set max buffer size with at least 1 byte to make sure SendData()/OnSend() logic be unified even when 
	/// no sending buffer is needed.
	void SetMaxSize(DWORD inMaxSize) { m_maxSize = (inMaxSize==0 ? 1 : inMaxSize); }
	
	BOOL HaveSpace() const { return m_curSize < m_maxSize; }
	BOOL IsDataSetEmpty() const
	{
#ifdef RLBTCP_ENABLE_DATA_PRIORITY
		DWORD i = IRtTransport::DP_MEDIUM;
		for (i=IRtTransport::DP_SYSTEM; i<IRtTransport::DP_NUMBER_OF_PRIORITIES; ++i)
		{
			if ( !m_sendDataSet[i].IsEmpty() )
				return FALSE;
		}
		return TRUE;
#else
		return m_sendDataSet[IRtTransport::DP_MEDIUM].IsEmpty();
#endif
	}
// 	BOOL IsEncodedDataEmpty() const { return m_encodedData==NULL; }

	void AddData(
		CRtMessageBlock* inData,
		DWORD inDataLength,
		IRtTransport::DataPriority inPriority, 
		BOOL inNeedAck);
	RtResult SendBuffer();
	RtResult SendEncodedData();
	void SendKeepAlive();
	void SendRtt(DWORD inTimestamp);
	BOOL OnRecvAck(SeqType inAck);
	void OnReconnect(SeqType inAck);

	void Release();
	void ReleaseEncodedData();

protected:
	CRtConnRlbTcp* m_conn;

	DWORD m_maxSize;
	DWORD m_curSize;
	SeqType m_seq;
	DataQueue m_sendDataSet[IRtTransport::DP_NUMBER_OF_PRIORITIES];
	DataQueue m_resendQueue;

	CRtMessageBlock* m_encodedData;

	static RlbTcpPduDataPoolType s_pduDataPool;
	
	friend class CRtConnRlbTcp;
	friend class CRtConnRlbTcpClient;
	friend class CRtConnRlbTcpServer;
};

#endif //!__RT_CONN_RLB_TCP_SENDBUFFER_H__

#endif // !RT_USE_OLD_CONN_WRAP
